package ve.com.wayoyo.wuml_case.DibujoDiagramas;

import java.util.ArrayList;

import android.graphics.Canvas;
import android.graphics.Point;

public abstract class Componente implements Cloneable {

	// Estados
	public final static int VOID_STATE = -1;
	public final static int IDLE = 0;
	public final static int SELECTED = 1;
	public final static int CONNECTING = 2;
	public final static int LINKED = 3;
	public final static int INSIDE_PACKAGE = 4;
	public final static int INSIDE_DEFAULT_PACKAGE = 5;
	public final static int INITIAL_NODE = 6;
	public final static int AVIABLE_NODE = 7;
	public final static int UNAVIABLE_NODE = 8;
	public final static int FINAL_NODE = 9;
	public final static int PATH_NODE = 10;
	

	protected Point Anchor; // Varibale que determina el punto de inicio del
							// componente.
	protected Point _centerPoint;
	protected String Titulo;
	protected int ID;
	protected int _currentState;
	protected String Tipo;
	protected ArrayList<CompConector> _conectorsBegining = new ArrayList<CompConector>();
	protected ArrayList<CompConector> _conectorsEnd = new ArrayList<CompConector>();

	// Para Cambiar
	protected BorderAnchors _topAnchors;
	protected BorderAnchors _leftAnchors;
	protected BorderAnchors _rightAnchors;
	protected BorderAnchors _bottomAnchors;

	// Nuevo metodo de conexion
	protected Point[] _connectionPoints;
	protected int[] _connectionPointsCost;

	protected float _width = 0;
	protected float _height = 80;
	protected boolean allowRecursivity = false;
	
	public Componente clone(){
		Componente result = null;
		try {
			result = (Componente) super.clone();
		} catch (CloneNotSupportedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}

	protected boolean isConnectable = true;
	
	public boolean isConnectable() {
		return isConnectable;
	}


	public void set_currentState(int _currentState) {
		this._currentState = _currentState;
	}
	
	public boolean isAllowRecursivity() {
		return allowRecursivity;
	}


	public void setAllowRecursivity(boolean allowRecursivity) {
		this.allowRecursivity = allowRecursivity;
	}


	public void set_width(float _width) {
		this._width = _width;
	}


	public float get_width() {
		return _width;
	}

	public float get_height() {
		return _height;
	}

	public Point getAnchor() {
		return Anchor;
	}

	public void setAnchor(Point anchor) {
		Anchor = anchor;
	}

	public Point get_centerPoint() {
		return _centerPoint;
	}

	public String getTitulo() {
		return Titulo;
	}

	public int getState() {
		return _currentState;
	}

	public abstract void setTitulo(String titulo);
	
	
	public int get_currentState() {
		return _currentState;
	}

	public int getID() {
		return this.ID;
	}

	public void setID(int iD) {
		ID = iD;
	}

	public String getTipo() {
		return Tipo;
	}

	public void setTipo(String tipo) {
		Tipo = tipo;
	}

	public void set_height(float _height) {
		this._height = _height;
	}

	public ArrayList<CompConector> get_conectorsBegining() {
		return _conectorsBegining;
	}

	public ArrayList<CompConector> get_conectorsEnd() {
		return _conectorsEnd;
	}

	public void removeFocus() {
		_currentState = IDLE;
		for (CompConector value : _conectorsBegining) {
			value.setState(CompConector.IDLE_STATE);
		}
	}

	public void mover(int distX, int distY) {
		Anchor.x += distX;
		Anchor.y += distY;
		actualizarAchorsPoints();
		actualizarPuntoCentral();
		for (CompConector value : _conectorsBegining) {
			value.actualizarRuta(this);
		}
		for (CompConector value : _conectorsEnd) {
			value.actualizarRuta(VistaDiagrama.getVista().getDiagrama()
					.getComponenteById(value.get_fatherId()));
		}
	}

	public BorderAnchors get_leftAnchors() {
		return _leftAnchors;
	}

	public BorderAnchors get_rightAnchors() {
		return _rightAnchors;
	}

	public BorderAnchors get_bottomAnchors() {
		return _bottomAnchors;
	}

	public BorderAnchors get_topAnchors() {
		return _topAnchors;
	}

	public abstract void Dibujar(Canvas c, boolean isFcoused,
			float globalScale, int offSetX, int offSetY);

	public abstract boolean CalcularVisibilidad(int offSetX, int offSetY,
			float GlobalScale);

	public abstract boolean calcularTouch(Point touch);

	public abstract CompConector calcularTouchConectores(Point touch);

	public abstract void actualizarAchorsPoints();

	public abstract void actualizarPuntoCentral();

	public abstract String generarDOM();

	public abstract String getConectorsDOM();

	public abstract void calculoLongitud();

	public Point requestConnectionPoint(CompConector connector, int mode,
			Point otherCompCenter) {
		/*
		 * Mode: 1-Padre 2-Hijo
		 */
		int lessCostPos = Integer.MAX_VALUE;
		float lessCost = Float.MAX_VALUE;
		float costPenalty = 1.5f;
		int orientation = 0;
		if (mode == 1) {
			if (connector.get_fatherConectorPort() != -1) {
				_connectionPointsCost[connector.get_fatherConectorPort()] -= 1;
			}
		} else {
			if (connector.get_childConectorPort() != -1) {
				_connectionPointsCost[connector.get_childConectorPort()] -= 1;
			}
		}
		for (int i = 0; i < _connectionPoints.length; i++) {
			if (((_connectionPointsCost[i] + 1) * costPenalty)
					* calcularDistEntrePuntos(_connectionPoints[i],
							otherCompCenter) < lessCost) {
				lessCost = ((_connectionPointsCost[i] + 1) * costPenalty)
						* calcularDistEntrePuntos(_connectionPoints[i],
								otherCompCenter);
				lessCostPos = i;
			}
		}
		if (lessCostPos < (_connectionPoints.length / 4)) {
			orientation = CompConector.ORIENTATION_TOP;
		} else if (lessCostPos < (_connectionPoints.length / 4) * 2) {
			orientation = CompConector.ORIENTATION_RIGHT;
		} else if (lessCostPos < (_connectionPoints.length / 4) * 3) {
			orientation = CompConector.ORIENTATION_BOTTOM;
		} else if (lessCostPos < _connectionPoints.length) {
			orientation = CompConector.ORIENTATION_LEFT;
		}
		if (mode == 1) {
			connector.set_fatherConectorPort(lessCostPos);
			connector.set_fatherOrientation(orientation);
		} else {
			connector.set_childConectorPort(lessCostPos);
			connector.set_childOrientation(orientation);
		}

		_connectionPointsCost[lessCostPos] += 1;
		return _connectionPoints[lessCostPos];
	}

	private int calcularDistEntrePuntos(Point a, Point b) {
		int respuesta = (int) Math.hypot(a.x - b.x, a.y - b.y);
		return respuesta;
	}

}
